import tensorflow as tf
import tensorflow.keras.layers as layers

"""
1.模型堆叠
最常见的模型类型就是堆叠
tf.keras.Sequential 模型
相当于构建网络拓补图
layers.Dense()是一个全连接网络
第一个入参，要求多少个神经元
第二个入参，激活函数时什么
一个简单的做分类的全连接网络层
一下为基础语法一层一层的添加
"""

model = tf.keras.Sequential()
model.add(layers.Dense(32, activation="relu"))
model.add(layers.Dense(32, activation="relu"))
model.add(layers.Dense(10, activation="softmax"))

"""
函数时的构建模型
函数时模型利用tf.keras.Input和tf.keras.Model构建
比tf.keras.Sequential模型要复杂的多，但是效果很好，可以同时/分段输入变量，分阶段输出数据
如果需要多余一个输出，那么需要选择函数式的模型
模型堆叠（.Sequential）vs 函数式模型（Model）
tf.keras.Sequential 模型是简单的堆叠，无法表示任意模型，使用keras的函数式模型可以构建复杂的模型拓补，
例如：
多输入模型
多输出模型
具有共享层的模型
具有非序列数据流的模型（比如说残差连接）
model是一层一层的定义网络的
例子如下：
"""
# 定义网络输入层,一般输入输入层的个数
x = tf.keras.Input(shape=(32,))
# 第一个隐藏层
h1 = layers.Dense(32,activation="relu")(x)
h2 = layers.Dense(32,activation="relu")(h1)
y = layers.Dense(10,activation="softmax")(h2)
model_sample_2 = tf.keras.models.Model(x,y)

model_sample_2.summary()
"""
在tf.keras.layers中主要的网络配置参数如下
activation 设置层的激活函数，迷人情况下系统不会应用任何激活函数
kernel_initializer和bias_initializer 创建层的权重（核和偏置）的初始化方案，默认为Glorot uniform
kernel_regularizer和bias_regularizer 应用层权重（核和偏置）的正则方案，例如L1或L2正则化，默认无正则


配置神经网络层
构建全连接层：             tf.keras.layers.Dense
构建2维卷积层：            tf.keras.layers.Conv2D
构建最大/平均池化层：       tf.keras.layers.MaxPooling2D/AveragePooling2D
构建循环神经网络层：        tf.keras.layers.RNN
构建LSTM网络层/LSTM unit:  tf.keras.layers.LSTM/tf.keras.layers.LSTMCell
构建GRU unit/网络：        tf.keras.layers.GRU/GRUCell
构建dropout层：            tf.keras.layers.Dropout
Embedding层：              tf.keras.layers.Embedding

Embedding层只能作为模型的第一层，嵌入层将正整数（下标）转换为具有固定大小的向量[[4],[20]] ->[[0.25,0.1], [0.6, -0.2]]
"""

"""
tf.keras.layers.Dense
units 神经元个数
activation 激活函数
kernel_initializer 创建层权重的初始化方案
bias_initializer 创建层权重偏置的初始化方案
kernel_regularizer 应用层权重的正则化方案
bias_regularizer 应用层偏置的正则化方案
activity_regularizer 施加在输出上的正则项，为Regularizer对象
kernel_constraint 施加在权重上的约束项
bias_constraint 施加在偏置上的约束项
"""
layers.Dense(32, activation=tf.sigmoid)
layers.Dense(32,kernel_initializer=tf.keras.initializers.he_normal)
layers.Dense(32,kernel_regularizer=tf.keras.regularizers.l2(0.01))

"""
tf.keras.layers.Conv2D
filters 卷积核的数目
kernel_size 卷积核的宽度和长度
strides 卷积的步长
padding 补0策略 
    padding="valid" 代表只进行有效的卷积，级对边界数据不进行处理。padding="same" 代表保留边界处的卷积结果，通常会导致输出的shape与输入的shape结果相同
activation 激活函数
data_format 数据格式为：channels_first 或者 channels_last 以128*128的RGB图像为例
channels_first应将数据组织为（3,128,128）
channels_last应将数据组织为（128,128,3）
改参数默认值是~/.keras/keras.json中的配置如果没有实质过则默认使用channels_last
"""
layers.Conv2D(64,[1,1],2,padding="same",activation="relu")

"""
tf.keras.layers.MaxPooling2D/AveragePooling2D
pool_size 池化kernel的大小，如矩阵（2,2）将使图片在两个维度上变为原长的一般。为整数意为哥哥维度值都为改数字
strides 步长
还包括 padding，data_format
"""
layers.MaxPooling2D(pool_size=(2, 2), strides=(2,1))
"""
tf.keras.layers.LSTM/tf.keras.layers.LSTMCell
units 单元数
input_shape (timestep,input_dim).timestep可以设置为None，input_dim为输入数据维度
return_sequence 为True时，返回全部序列，为False时，返回输出序列中的最后一个cell的输出 
"""
inputs = tf.keras.Input(shape=(3, 1))
lstm = layers.LSTM(1,return_sequences=True)(inputs)
model_lstm_1 = tf.keras.models.Model(inputs=inputs,outputs=lstm)
#LSTMCell
x = tf.keras.Input((None,3))
y = layers.RNN(layers.LSTMCell(16))(x)
model_lstm_3 = tf.keras.models.Model(x,y)
